﻿// -----------------------------------------------------------------------
// <copyright file="PrivateReflectionWrapper.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;

namespace FxCopContrib.Experimental.RegexCop
{
    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class PrivateReflectionWrapper
    {
        private Type wrappedType;
        protected object wrappedObject;

        private Dictionary<string, object> cachedProperties = new Dictionary<string, object>();

        protected PrivateReflectionWrapper(Type wrappedType)
        {
            this.wrappedType = wrappedType;
        }

        protected PrivateReflectionWrapper(Type wrappedType, object wrappedObject) : this(wrappedType)
        {
            this.wrappedObject = wrappedObject;
        }

        private void SetWrappedObject(object wrappedObject)
        {
            this.wrappedObject = wrappedObject;
        }

        protected T GetFieldValue<T>(string name)
        {
            object result;
            if (!cachedProperties.TryGetValue(name, out result))
            {
                result = this.wrappedType.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(wrappedObject);
                cachedProperties.Add(name, result);
            }
            return (T)result;
        }

        protected IEnumerable<T> ToEnumerable<T>(string name)
            where T : PrivateReflectionWrapper, new()
        {
            IEnumerable list = GetFieldValue<IEnumerable>(name);
            if (list != null)
            {
                foreach (var item in list)
                {
                    T result = new T();
                    result.SetWrappedObject(item);
                    yield return result;
                }
            }
        }
    }
}
